package com.gebro.classifier;

import java.util.ArrayList;
import java.util.List;



/**
 * 
 * 
 * 
 * 
 * @author hadi.elmougy
 *
 */
public class Matrix {

	private List<MatrixElement> elements;

	/**
	 * 
	 * 
	 * 
	 * @param elements
	 */
	public Matrix(List<MatrixElement> elements) {
		this.elements = elements;
	}

	/**
	 * 
	 * 
	 * 
	 */
	public Matrix() {
		elements = new ArrayList<MatrixElement>();
	}

	/**
	 * 
	 * 
	 * 
	 * @param src
	 * @param point
	 * @return
	 */
	public static Matrix tile(Matrix src, Point point) {
		Matrix m = new Matrix();
		MatrixElement el;
		for (int i = 0; i < src.getLength(); i++) {
			el = new MatrixElement(null, point);
			m.addElement(el);
		}
		return m;
	}

	
	
	/**
	 * 
	 * 
	 * 
	 * 
	 * @return
	 */
	public static Matrix newMatrix() {
		return new Matrix();
	}

	
	/**
	 * 
	 * 
	 * 
	 * 
	 * @param el
	 */
	public void addElement(MatrixElement el) {
		elements.add(el);
	}

	
	
	/**
	 * 
	 * 
	 * 
	 * @return
	 */
	public int getLength() {
		return this.elements.size();
	}

	
	
	/**
	 * 
	 * 
	 * 
	 * 
	 * @return
	 */
	public double[][] asArray() {
		double[][] result = new double[getLength()][2];
		for (int i = 0; i < getLength(); i++) {
			MatrixElement el = elements.get(i);
			result[i][0] = el.getX();
			result[i][1] = el.getY();
		}
		return result;
	}

	
	
	/**
	 * 
	 * 
	 * 
	 * @param matrix
	 * @return
	 */
	public Matrix subtract(Matrix matrix) {

		if (this.getLength() != matrix.getLength()) {
			throw new IllegalStateException(
					"Arrays dimensions are not in the same size");
		}

		Matrix m = new Matrix();
		for (int i = 0; i < this.getLength(); i++) {
			MatrixElement localElm = this.elements.get(i);
			MatrixElement elm = matrix.getElements().get(i);
			double x = localElm.getX() - elm.getX();
			double y = localElm.getY() - elm.getY();
			Point p = new Point(x, y);
			MatrixElement el = new MatrixElement(elm.getLabel(), p);
			m.addElement(el);
		}
		return m;

	}

	
	
	/**
	 * 
	 * 
	 * 
	 * @return
	 */
	public List<MatrixElement> getElements() {
		return elements;
	}

	
	
	/**
	 * 
	 * 
	 * 
	 * 
	 * @param p
	 * @return
	 */
	public Matrix power(double p) {
		int m1cols = this.getLength();
		Matrix m = new Matrix();

		for (int i = 0; i < m1cols; i++) {
			MatrixElement prevEl = this.getElements().get(i);
			double x = Math.pow(prevEl.getX(), p);
			double y = Math.pow(prevEl.getY(), p);
			MatrixElement el = new MatrixElement(this.getElements().get(i)
					.getLabel(), new Point(x, y));
			m.addElement(el);
		}

		return m;
	}

}
